package com.ji.protostuff;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.DefaultIdStrategy;
import io.protostuff.runtime.Delegate;
import io.protostuff.runtime.RuntimeEnv;
import io.protostuff.runtime.RuntimeSchema;

/**
 * title:
 * author:looake
 * since:2018/6/28
 */
public class ProtoBufUtil {

    private static final Delegate<java.sql.Timestamp> TIMESTAMP_DELEGATE = new TimestampDelegate();
    private static final Delegate<java.sql.Date> DATE_DELEGATE = new DateDelegate();
    private static final Delegate<java.sql.Time> TIME_DELEGATE = new TimeDelegate();

    private final static DefaultIdStrategy idStrategy = ((DefaultIdStrategy) RuntimeEnv.ID_STRATEGY);

    static {
        idStrategy.registerDelegate(TIMESTAMP_DELEGATE);
        idStrategy.registerDelegate(DATE_DELEGATE);
        idStrategy.registerDelegate(TIME_DELEGATE);
    }

    /**
     * 序列化对象
     *
     * @param obj 需要序更列化的对象
     * @return byte []
     */
    public static byte[] serialize(Object obj) {
        if (obj == null) {
            return null;
        }
        Class cls = obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema schema = RuntimeSchema.getSchema(cls, idStrategy);
            return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
    }

    /**
     * 反序列化对象
     *
     * @param bytes 需要反序列化的byte []
     * @param clazz
     * @return 对象
     */
    public static <T> T deserialize(byte[] bytes, Class<T> clazz) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        try {
            Schema<T> schema = RuntimeSchema.getSchema(clazz, idStrategy);
            T message = schema.newMessage();
            ProtostuffIOUtil.mergeFrom(bytes, message, schema);
            return message;
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

}
